package com.naiterui.ehp.bs.b2c.address.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.beans.BeanUtil;
import com.naiterui.ehp.bs.b2c.address.constants.AddrConstants;
import com.naiterui.ehp.bs.b2c.address.entity.City;
import com.naiterui.ehp.bs.b2c.address.entity.ShippingInfo;
import com.naiterui.ehp.bs.b2c.address.exception.AddrExceptionCodes;
import com.naiterui.ehp.bs.b2c.address.repository.CityRepository;
import com.naiterui.ehp.bs.b2c.address.repository.ShippingInfoRepository;
import com.naiterui.ehp.bs.b2c.address.service.IShippingInfoService;
import com.naiterui.ehp.bs.b2c.address.vo.ShippingInfoDetailVO;
import com.naiterui.ehp.bs.b2c.address.vo.ShippingInfoParamVO;
import com.naiterui.ehp.bs.b2c.address.vo.ShippingInfoVO;
import com.naiterui.ehp.bs.b2c.common.bo.address.ShippingInfoBO;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ShippingInfoServiceImpl implements IShippingInfoService {

    /**
     * 城市类型-区层级深度
     */
    private static final Integer CITY_TYPE_COUNTRY_DEPTH = 3;

    @Autowired
    private CityRepository cityRepository;
    @Autowired
    private ShippingInfoRepository shippingInfoRepository;

    @Override
    public List<ShippingInfoVO> getShippingInfoList(Long userId) {
        List<ShippingInfo> shippingInfoList = this.shippingInfoRepository.findAllByUserId(userId);

        List<ShippingInfoVO> list = new ArrayList<>();
        if (shippingInfoList != null && !shippingInfoList.isEmpty()) {
            BeanUtil.copyList(shippingInfoList, list, ShippingInfoVO.class);
        }
        return list;
    }

    @Override
    public ShippingInfoDetailVO getShippingInfo(Long userId, Long shippingInfoId) {
        ShippingInfo shippingInfo = this.shippingInfoRepository.findByIdAndUserId(shippingInfoId, userId);
        if (shippingInfo == null) {
            return null;
        }
        City conty = this.cityRepository.get(shippingInfo.getCityId());
        City city = this.cityRepository.get(conty.getParentId());
        ShippingInfoDetailVO vo = new ShippingInfoDetailVO();
        BeanUtils.copyProperties(shippingInfo, vo);
        vo.setProvinceId(city.getParentId());
        vo.setTownId(conty.getParentId());
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShippingInfoVO saveShippingInfo(Long userId, ShippingInfoParamVO shippingInfoParamVO) throws BusinessException {
        ShippingInfoVO shippingInfoVO = new ShippingInfoVO();
        ShippingInfo shippingInfo;

        boolean isCreate = false;
        // 新增
        if (shippingInfoParamVO.getId() == null) {
            isCreate = true;
            // 修改地址信息
            shippingInfo = new ShippingInfo();
            shippingInfo.setCreatedAt(new Date());
            shippingInfo.setCreatedBy("system");
        } else {
            shippingInfo = this.shippingInfoRepository.findByIdAndUserId(shippingInfoParamVO.getId(), userId);
            if (shippingInfo == null) {
                log.warn("地址ID不存在userId:{}, shippingInfoId:{}", userId, shippingInfoParamVO.getId());
                throw new BusinessException(AddrExceptionCodes.SHIPPING_INFO_ID_INVLID);
            }
            shippingInfo.setChangedAt(new Date());
            shippingInfo.setChangedBy("system");
        }

        // 修改地址信息

        BeanUtils.copyProperties(shippingInfoParamVO, shippingInfo);
        shippingInfo.setUserId(userId);
        // 根据城市ID查询城市信息
        Optional<City> city = this.cityRepository.findById(shippingInfoParamVO.getCityId());
        if (!city.isPresent()) {
            log.warn("城市ID无效 {}", shippingInfoParamVO.getCityId());
            throw new BusinessException(AddrExceptionCodes.CITY_ID_INVLID);
        }
        String[] parentNameArr = city.get().getParentName().split(",");
        if (!AddrConstants.CITY_TYPE_COUNTRY.equals(city.get().getType()) || CITY_TYPE_COUNTRY_DEPTH > parentNameArr.length) {
            log.warn("城市类型或城市层级深度错误, userId:{}, cityId:{}, type:{}", userId, city.get().getId(), city.get().getType());
            throw new BusinessException(AddrExceptionCodes.CITY_TYPE_ERROR);
        }
        shippingInfo.setProvince(parentNameArr[1]);
        shippingInfo.setCity(parentNameArr[2]);
        shippingInfo.setCounty(city.get().getName());
        shippingInfo.setChangedAt(new Date());
        shippingInfo.setChangedBy("system");
        if (AddrConstants.DEFAULT_ADDR_SELECTED.equals(shippingInfoParamVO.getDefaultAddr())) {
            // 设置其他取消选中
            this.shippingInfoRepository.updateDefaultAddr(AddrConstants.DEFAULT_ADDR_UNSELECTED, userId, AddrConstants.DEFAULT_ADDR_SELECTED);
        }
        if (isCreate) {
            // 保存提交的地址
            this.shippingInfoRepository.save(shippingInfo);
        } else {
            this.shippingInfoRepository.update(shippingInfo);
        }
        BeanUtils.copyProperties(shippingInfo, shippingInfoVO);

        return shippingInfoVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteShippingInfo(Long userId, Long shippingInfoId) {
        this.shippingInfoRepository.deleteByIdAndUserId(shippingInfoId, userId);
    }

    @Override
    public ShippingInfoBO getDefaultShippingInfo(Long userId) {
        ShippingInfo shippingInfo = this.shippingInfoRepository.findByUserIdAndDefaultAddr(userId, AddrConstants.DEFAUTL_ADDR);
        if (shippingInfo == null) {
            return null;
        }
        ShippingInfoBO bo = new ShippingInfoBO();
        BeanUtils.copyProperties(shippingInfo, bo);
        bo.setShippingInfoId(shippingInfo.getId());
        return bo;
    }

    @Override
    public ShippingInfoBO getShippingInfoById(Long shippingInfoId, Long userId) {
        ShippingInfo shippingInfo = this.shippingInfoRepository.findByIdAndUserId(shippingInfoId, userId);
        if (shippingInfo == null) {
            return null;
        }
        ShippingInfoBO bo = new ShippingInfoBO();
        BeanUtils.copyProperties(shippingInfo, bo);
        bo.setShippingInfoId(shippingInfo.getId());
        return bo;
    }

}
